package bid

import (
	"errors"
	"fmt"
	"github.com/gomodule/redigo/redis"
	"strconv"
	"strings"
	"time"
	config "wx-api/adx-bid/config"
	"wx-api/adx-bid/model/m_channelslot"
	"wx-api/adx-bid/models/bid/BidModel"
	"wx-api/adx-bid/utils"
)

type BudgetReqLimit struct{}

func (z *BudgetReqLimit) IsLimit(d_info *m_channelslot.ChannelSlot, d *BidModel.BidRequest_Device) error {
	if d_info.ReqNum == 0 {
		return nil
	}
	if d == nil {
		return errors.New("BudgetReqLimit device is nil")
	}
	kfield := z.GetDid(d)
	if kfield == "" {
		return errors.New("BudgetReqLimit device id is empty")
	}
	hkey := "req-limit-" + time.Now().Format("2006-01-02") + "-" + d_info.DspId + "-" + d_info.Uqid
	tcv, ok, err := z.GetRedisDid(hkey, kfield)
	if !ok {
		if err != nil {
			return errors.New(hkey + " BudgetReqLimit:dsp_cheat1:" + err.Error())
		}
		return errors.New(hkey + " BudgetReqLimit:dsp_cheat2:" + hkey + "=" + kfield)
	}
	if tcv < int64(d_info.ReqNum) {
		return nil
	}
	return errors.New(hkey + " BudgetReqLimit:dsp_cheat3:" + hkey + "=" + kfield + "||" + strconv.Itoa(int(tcv)) + "=" + strconv.Itoa(d_info.ReqNum))
}
func (z *BudgetReqLimit) GetRedisDid(hkey, kfield string) (int64, bool, error) {
	conn := config.AdxRedisCheat.Get()
	if conn == nil {
		fmt.Println("BudgetReqLimit adxCheat is nil")
		return 0, false, errors.New("db is nil")
	}
	defer conn.Close()
	kfield = utils.MD5(kfield)
	ret, err := redis.Int64(conn.Do("HGET", hkey, kfield))

	if err != nil && !errors.Is(err, redis.ErrNil) {
		return 0, false, errors.New("TxGetAutiKey db:" + err.Error())
	}
	return ret, true, nil
}
func (z *BudgetReqLimit) SetRedisDid(d_info *m_channelslot.ChannelSlot, d *BidModel.BidRequest_Device) error {
	if d_info.ReqNum == 0 {
		return nil
	}
	if d == nil {
		return errors.New("BudgetReqLimit SetRedisDid device is nil")
	}
	kfield := z.GetDid(d)
	if kfield == "" {
		return errors.New("BudgetReqLimit SetRedisDid device id is empty")
	}
	hkey := d_info.DspId + "-" + d_info.Uqid

	conn := config.AdxRedisCheat.Get()
	if conn == nil {
		return errors.New("BudgetReqLimit SetRedisDid is nil")
	}
	kfield = utils.MD5(kfield)
	_, err := conn.Do("HINCRBY", hkey, kfield, 1)
	if err != nil && !errors.Is(err, redis.ErrNil) {
		return errors.New("BudgetReqLimit SetRedisDid err:" + err.Error())
	}
	defer conn.Close()
	return nil
}

func (z *BudgetReqLimit) GetDid(d *BidModel.BidRequest_Device) string {
	os := strings.ToLower(d.GetOs())
	if os == "ios" {
		if d.GetIdfaMd5() != "" {
			return d.GetIdfaMd5()
		}
		if d.GetIdfa() != "" {
			return d.GetIdfa()
		}
		if d.GetIdfaSha1() != "" {
			return d.GetIdfaSha1()
		}
		if len(d.GetCaids()) > 0 {
			for _, caid := range d.GetCaids() {
				if caid.GetCaid() != "" {
					return caid.GetCaid()
				}
				if caid.GetCaidMd5() != "" {
					return caid.GetCaidMd5()
				}
			}
		}
		if d.GetIdfv() != "" {
			return d.GetIdfv()
		}
		if d.GetGaid() != "" {
			return d.GetGaid()
		}
	} else {
		if d.GetOaidMd5() != "" {
			return d.GetOaidMd5()
		}
		if d.GetImeiMd5() != "" {
			return d.GetImeiMd5()
		}
		if d.GetOaid() != "" {
			return d.GetOaid()
		}
		if d.GetImei() != "" {
			return d.GetImei()
		}
		if d.GetImeiSha1() != "" {
			return d.GetImeiSha1()
		}
		if d.GetAndroidIdMd5() != "" {
			return d.GetAndroidIdMd5()
		}
		if d.GetMacMd5() != "" {
			return d.GetMacMd5()
		}
		if d.GetAndroidId() != "" {
			return d.GetAndroidId()
		}
		if d.GetAndroidIdSha1() != "" {
			return d.GetAndroidIdSha1()
		}
		if d.GetMac() != "" {
			return d.GetMac()
		}
		if d.GetMacSha1() != "" {
			return d.GetMacSha1()
		}
	}
	return ""
}
